﻿using System;
using System.Windows;

namespace AddressManager.Common.Util
{
    public static class XamlHelper
    {
        /// <summary>
        /// Gets the datacontext of an object of the given type
        /// </summary>
        /// <typeparam name="T">Target type of the objects datacontext</typeparam>
        /// <param name="o">Object o</param>
        /// <returns>The datacontext of o as the given type T</returns>
        public static T GetDataContext<T>(this object o)
        {
            if (o == null) throw new ArgumentNullException("o");

            var element = o.Cast<FrameworkElement>();
            if (element.DataContext == null) throw new ArgumentException("Tried to get the DataContext of an object but the DataContext was null.");
            if (element.DataContext is T)
            {
                return (T)element.DataContext;
            }
            else
            {
                throw new Exception("Tried to get the DataContext of an object but the DataContext was not of the expected type. expected: " + typeof(T) + " actual: " + element.DataContext.GetType().ToString());
            }
        }

        /// <summary>
        /// Indicates whether a given object has the datacontext of a given type
        /// </summary>
        /// <typeparam name="T">Target type T of the objects datacontext</typeparam>
        /// <param name="o">Object o</param>
        /// <returns><c>true</c> if the datacontext is of the given type or <c>false</c> if not</returns>
        public static bool HasDataContext<T>(this object o)
        {
            if (o is FrameworkElement)
            {
                return (o as FrameworkElement).DataContext is T;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Casts a given object o to a given type T
        /// </summary>
        /// <typeparam name="T">Target type T</typeparam>
        /// <param name="o">Object to cast</param>
        /// <returns>Object o as target type T</returns>
        public static T Cast<T>(this object o)
        {
            if (o == null) throw new ArgumentNullException("o");

            if (o is T)
            {
                return (T)o;
            }
            else
            {
                throw new Exception("Tried to cast an object but it was not of the expected type. expected: " + typeof(T) + " actual: " + o.GetType());
            }
        }
    }
}